package com.wang.fuxi;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

public class Test2 {
	public static void main(String[] args) {
		/**
		 *	正则表达式：是跨语言平台。JS、Java。。。。
		 *		1. 概念：
		 *				就是一个字符串匹配机制。
		 *		2. 语法：
		 *				?,*,+,\d,\w 都是等价字符
						?等价于匹配长度{0,1}
						*等价于匹配长度{0,}
						+等价于匹配长度{1,}	
						\d等价于[0-9]	匹配一个任意数字
						\D等价于[^0-9]	匹配一个任意非数字字符
						\w等价于[A-Za-z_0-9]
						\W等价于[^A-Za-z_0-9]。
						常用运算符与表达式:
						^ 开始
						() 域段
						[] 包含,默认是一个字符长度
						[^] 不包含,默认是一个字符长度
						{n,m} 匹配长度在n到m之间
						{n,} 匹配长度大于等于n
						. 任何单个字符(\. 字符点)
						| 或
						\ 转义
						$ 结尾
						[A-Z] 26个大写字母
						[a-z] 26个小写字母
						[0-9] 0至9数字
						[A-Za-z0-9] 26个大写字母、26个小写字母和0至9数字
						^[0-9]+(.[0-9]{1,2})?$ :表示匹配 0-9的数字1个到任一个 和（ . 和 0-9 一个或者两个）括号中可以有0或者1个
		 *		3. 作用：
		 *			校验做一些要求判断，例如：账号规范、密码规范、身份证、电话号码等
		 *		4. 使用：	
		 *			Java中String的几个方法用：
		 *			boolean matches(String regex)
		 *			String[] split(String regex)
		 *			void replaceAll(String regex,String str)
		 *			void replaceFirst(String regex,String str)
		 *			JS:也能用
				5. 以后用到正则表达式的时候，能百度就百度
				6. 参见Matcher 和 Pattern类，加强正则表达式
		 */
		/*
		 * 注意：
		 * 	第1个^表示正则表达式开始
		 * 	第2个^表示正则表达式中的非（除了）的意思
		 *  最后一个$:表示正则表达式结束
		 */
		String regex = "^[^0-9]$";//表示匹配0~9之间任意一个字符
		String str = "123";
		boolean matches = str.matches(regex);//false 判断当前str对象是不是满足regex规则		
		regex = "[abcd]*";////表示匹配abcd之间任意0个到多个字符
		str = "ab";
		boolean matches3 = str.matches(regex);//true		
		//请验证手机号：1（第二位没有：0，1，2） 共11位
		regex = "^[1][3-9][0-9]{9}$";
		str = "13380806969";
		boolean matches2 = str.matches(regex);//true
		/**
		 *	获取随机数：
		 *		1. 应用： 验证码，彩票、抽奖、摇号、贪吃蛇、砸地鼠、。。。。。
		 *		2. 获取方式4种：
		 *			掌握；前两种
		 *			1.	ThreadLocalRandom类：推荐使用
		 *				1.1 获取对象
		 *					static ThreadLocalRandom current()  
		 *				1.2 调用方法：
		 *					int nextInt(int origin, int bound)  生成随机数范围：[origin,bound);
		 *		2.	UUID： 表示128位二进制值，32位十六进制	推荐使用		
		 *			一般用来做数据库唯一标识符：主键（primary key）
		 *			使用：
		 *					static UUID randomUUID();
							UUID.randomUUID();
				==============================不建议用================================
		 *		3.	Random类：不推荐用
		 *				1.创建对象：
		 *					Random() 创建一个新的随机数生成器。  
							Random(long seed) 使用单个 long种子创建一个新的随机数生成器。  	不推荐用long种子，System.currentTimeMillis();
						2. 调用方法
		 *					int nextInt() 返回值为 double值为正号，大于等于 0.0 ，小于 1.0 。  生成随机数范围：[0.0,1.0);
							int nextInt(int bound)  生成直到范围内的随机数	 生成随机数范围：[0,bound);
		 *		4.	Math类：	
						调用方法：
						static double random() 返回值为 double值为正号，大于等于 0.0 ，小于 1.0 。[0.0,1.0)  
		 *		
		 */
		/*
		 * 1.	ThreadLocalRandom类：推荐使用
 *				1.1 获取对象
 *					static ThreadLocalRandom current()  
 *				1.2 调用方法：
 *					int nextInt(int origin, int bound)  生成随机数范围：[origin,bound);
		 */
		ThreadLocalRandom current = ThreadLocalRandom.current();
		//调用方法获取指定范围内的随机数
		int nextInt = current.nextInt(3,8);//7 生成[3,8)
		/*
		 * 2.	UUID： 表示128位二进制值，32位十六进制	推荐使用		
 *			一般用来做数据库唯一标识符：主键（primary key）
 *			使用：
 *					static UUID randomUUID();
					UUID.randomUUID();
		 */
		UUID randomUUID = UUID.randomUUID();//9221df25-9926-4536-aa96-239b76672733
		//扩展：下划线没有实际作用，就是让位数可读性好
		System.out.println(1234_1234_111L);//12341234111
		/*
		 * 了解使用：
		 * 3.	Random类：不推荐用
 *				1.创建对象：
 *					Random() 创建一个新的随机数生成器。  
					Random(long seed) 使用单个 long种子创建一个新的随机数生成器。  	不推荐用long种子，System.currentTimeMillis();
				2. 调用方法
 *					int nextInt() 生成int范围内的任意一个数字。  
					int nextInt(int bound)  生成直到范围内的随机数	 生成随机数范围：[0,bound);
		 */
		Random random = new Random();
		//调用方法
		int nextInt2 = random.nextInt();//-268377158
		//生成3~7：3 4 5 6 7 
		int nextInt3 = random.nextInt(5);//生成[0,5)之间的数字
		System.out.println(nextInt3 + 3);//加上3就是生成的是3~7之间的数
		//	Random(long seed) 使用单个 long种子创建一个新的随机数生成器。
//		Random random2 = new Random(1L);//如果种子是固定的，则随机数是固定的，所以需要种子可变
		Random random2 = new Random(System.currentTimeMillis());//如果种子是固定的，则随机数是固定的，所以需要种子可变
		int nextInt4 = random2.nextInt();//-1187847487
		/**
		 *	BigInteger: 精度比long高
		 *	BigDecimal: 精度比double高，一般在金融产品，银行项目、科研项目、航空航天 等用该类，代替double
		 */
		//BigInteger:构造方法:BigInteger(String val) 
		/*
		 * 构造方法：
		 *		BigDecimal(double val)  
		 *		BigDecimal(int val) 
		 *		BigDecimal(String val)  建议使用这种方式创建，因为其他方式有可能会有精度丢失
		 */
		BigDecimal bigDecimal = new BigDecimal("3.0014");
		BigDecimal bigDecimal2 = new BigDecimal("0.000125");
		//加法：BigDecimal add(BigDecimal augend) 返回 BigDecimal ，其值是 (this + augend)  
		BigDecimal add = bigDecimal.add(bigDecimal2);//3.001525
		//减法：BigDecimal subtract(BigDecimal subtrahend) 返回 BigDecimal ，其值是 (this - subtrahend) 
		BigDecimal subtract = bigDecimal.subtract(bigDecimal2);//3.001275		
		//乘法：BigDecimal multiply(BigDecimal multiplicand) 返回 BigDecimal ，其值是 (this × multiplicand)， 
		BigDecimal multiply = bigDecimal.multiply(bigDecimal2);//0.0003751750
		//除法：BigDecimal divide(BigDecimal divisor)返回BigDecimal ，其值为(this / divisor 
//				BigDecimal divide = bigDecimal2.divide(bigDecimal);
//				System.out.println(divide); //java.lang.ArithmeticException
		/*
		 * 当精度超出BigDecimal表示范围的时候，就需要用divide方法重载方法
		 * public BigDecimal divide(BigDecimal divisor,RoundingMode roundingMode)
		 * 	RoundingMode：就是一个枚举类，是决定取舍方式的。使用方式：枚举名.字段；
		 */
		BigDecimal divide = bigDecimal2.divide(bigDecimal,RoundingMode.CEILING);
		System.out.println(divide);//0.000042
		/**
		 *	Math: 数学相关的类。主要是数学相关的方法。
		 */
		//调用常量:	static double PI  
		System.out.println(Math.PI);//3.141592653589793
		//调用方法（都是static修饰的）
		//static double abs(double a)返回值为 double绝对值。  
		System.out.println(Math.abs(-3.14));//3.14
		//static double ceil(double a)  天花板，向上取整
		System.out.println(Math.ceil(3.1));//4.0
		//static double floor(double a)  地板，向下取整
		System.out.println(Math.floor(3.9999));//3.0
		//static long/int round(double a)  四舍五入
		System.out.println(Math.round(3.4));//3
		//static double max(double a, double b)返回两个 double值中的较大值。  
		//static double min(double a, double b)返回两个 double值中的较小值。
		/**
		 *	异常：
		 *		1. 概念： 就是程序中一种不正常的情况。就是一种状态或标志，我们就是根据不同的异常类型，能够得知处理异常的方式。
		 *		2. 异常分类：
				 *	Throwable（基类）
				 *		|
				 *		|---- Error 错误，我们程序无法处理。如，内层溢出，网络断线
				 *		|
				 *		|---- Exception 异常，我们可以通过程序处理
				 *				  |
				 *			   	  |---	RuntimeException 运行时异常，运行期才能知道
				 *				  |				|
				 *			   	  |			NullPointerException 空指针异常
				 *				  |
				 *				  |---	非运行时异常
				 *
		 *		3. 异常在Java中的处理方式：
		 *			在Java中处理异常的方式是：首先，发生异常的时候，会先看当前异常代码处是否有处理异常的代码，如果有，则会执行处理异常的代码
		 *			处理完异常后，会继续向下执行。如果没有，则会向调用着抛出该异常，如果调用者有处理方式，则会正常执行，如果没有会继续再向调用者
		 *			抛出，直到抛出给JVM为止，而JVM处理异常的方式是，打印异常信息到控制台，然后，退出JVM。
		 *		4. 处理异常方式：
		 *				try{
		 *					异常可能发生的代码
		 *				}catch(可能的异常类1   变量){//当发生异常的时候，JVM会自动根据异常类型，创建一个异常对象，将对象的地址存放到变量中
		 *					处理异常的操作：
		 *					1. 打印异常的信息到控制台；
								//处理方式1 ：打印异常原因    一般处理后给前台页面返回，给用户提示问题原因 
								String message = e.getMessage();
								System.out.println(message);
								//2. 处理方式2：打印日志  推荐 给程序员看的，帮助程序员定位错误的位置
								e.printStackTrace();	
								//3. 处理方式3 ：异常类型和异常原因
								String str = e.toString();
								System.out.println(str);
							2. 可以把异常信息保存到一个文件中，可以持久的存储起来；； 因为实际项目有可能有很多异常打印到控制台，不能随时关注，这时就需要将日志保存，
							3. 可以抓住异常之后，向外在抛出给调用者，就是谁调用谁处理。
								用关键字throws,用在（）后｛｝前
								多个异常逗号隔开，顺序无所谓。
		 *				}catch(可能的异常类2   变量){//注意：异常类型2 必须是异常类型1的父类或者不相干
		 *					处理方式同上
		 *				}.....
		 *				finally{
		 *					不管上面的上面的执行情况是怎样的，finally代码永远都会执行
		 *					一般只是释放资源，不写业务逻辑代码。如，关流	
		 *				}
		 *		5. 异常处理原则：
		 *				1. 尽可能将异常细化处理，因为不同的异常处理方式不同
		 *				2. 异常在catch的时候，必须保证父类异常在下面 ，子类异常在上面。或者几个异常没有任何关系的顺序无所谓
		 */
		/**
		 *	1. 进程：就是一个应用程序，是一大堆代码
		 *
		 *	2. 线程：线程是进程中的最小单位，一小堆代码。线程是一个独立的功能。每一个线程都有自己独立的内存区域，例如，线程计数器。
		 *			在当前进程中的所有线程，都会共享当前进程的共用内存区
		 *
		 *	3. 多线程作用：
		 *			可以更好的利用硬件资源，更好的利用多核心优势，提高程序的执行效率。
		 *
		 *	4. 语法：
		 *		Thread类，重写一个业务run方法,start方法启动线程后，每一个线程都是一个独立的功能，相互间不影响。
		 *		实现线程方式两种：
		 *			1. 继承Thread类
		 *				步骤：
		 *					1. 写一个线程类XxxThread extends Thread类
		 *					2. 重写run()方法（该方法是业务方法，启动线程后，会自动执行该方法）
		 *					3. 写一个测试类，在测试类中创建线程对象，调用对象的start()启动线程
		 *			2. 实现Runnable接口
		 *				步骤：
		 *					1. 写一个实现业务类XxxRunnableImpl implements Runnable接口
		 *					2. 重写run()方法（该方法是业务方法，启动线程后，会自动执行该方法）
		 *					3. 写一个测试类，在测试类中
		 *						先创建业务类对象
		 *						再创建线程对象，并且将业务类对象作为参数传入线程的构造方法中，调用线程对象的start()启动线程
		 *		以后都用实现的方式，因为Java中单继承多实现，实现的扩展性强
		 *	5. Thread中常用方法：
		 *			1. 构造方法：
		 *					Thread() 创建一个新的 Thread对象。  
							Thread(String name) 创建一个新的有指定线程名的 Thread对象。  
							Thread(Runnable target)  将Runnable业务类对象作为参数，创建一个新的 Thread对象。    
							Thread(Runnable target, String name) 将Runnable业务类对象作为参数，创建一个新的有指定线程名的 Thread对象。  
		 *			2. 普通方法：
		 *					1. static Thread  currentThread() 返回对当前正在执行的线程对象的引用。  
							2.        String  getName() 返回此线程的名称。 
							3.        void    setName(String name) 设置线程对象的名字   
							4.        void    setPriority(int newPriority)   设置线程对象的优先级
							5.        int     getPriority()  获取线程的优先级
									              1-10，越小优先级越高，执行越早，越大就执行越晚
									              5是默认优先级。
									                                    当前线程的优先级与创建线程对象的环境的优先级一致
							6.        boolean isDaemon() 判断这个线程是否是守护线程。  GC是守护线程
												     一个线程的默认状态和创建它的环境线程状态一致
							7. 		  void    setDaemon(boolean on) 将当前线程设置为守护线程   
								                                            活跃的线程不能设置为守护线程
							8.        void    join() 等待join线程执行完后，再执行当前线程
							9.        void    join(long millis)等待join线程线程死亡最多 millis毫秒。  
							10.static void    sleep(long millis)  阻塞当前线程指定的毫秒数后再执行
												  一般用来模拟网络延迟，可以做计时器，还可以做倒计时
												  以下在在多线程中常用
							11.       void    interrupt() 中断这个线程。  在多线程中常用
							12.static boolean interrupted() 测试当前线程是否中断。  在多线程中常用
							13.       boolean isAlive() 测试这个线程是否活着。 
							14.  Thread.State getState() 返回此线程的状态。  //枚举
							15.       long getId() 返回此线程的标识符。  			
		 	6. 线程同步方式：
				6.1 为什么？为了保证业务逻辑合理性
				6.2 三种方式：
						一、悲观锁：考虑的最坏的情况，每一次都会有线程安全问题。效率低下
							1. 同步代码块
								语法：
								synchronized(同步对象){//必须保证：几个有安全问题的线程对象看到的都是统一对象
									有线程安全问题代码
								}
							2. 同步方法
								语法：直接在方法的修饰符位置写上 synchronized在返回值前面
								如果方法是static修饰的 ：    同步的是 当前类.class
								如果方法是非static修饰的：同步的是 this
						二、乐观锁：考虑的是最好的情况，没有安全问题。一旦碰到线程安全问题，才启用锁机制。底层使用的是自旋机制
							3. 锁机制 Lock接口的实现类ReentrantLock
									构造方法：
										1. ReentrantLock() 创建一个 ReentrantLock的实例。   不要公平机制。效率高
										2. ReentrantLock(boolean fair) 根据给定的公平政策创建一个 ReentrantLock的实例。  理论上获取锁的几率是相同的
									 class X {
									   private final ReentrantLock lock = new ReentrantLock();
									   public void m() { 
									     lock.lock();  // 上锁
									     try {
									       	//有线程安全问题的代码
									     } finally {
									       lock.unlock();//释放锁
									     }
									   }
									 }
				6.3 同步对象：
					什么时候可以保证只有一个对象的情况？
					1. static 静态区，只有一份
					2. 字节码文件只有一份在元空间
				6.4 注意：
					1. 必须保证几个线程对象看到的是同一个同步对象（一般使用当前类的字节码文件）
					2. 线程同步的原则：最小范围原则，为了保证执行效率
		 * 卖票线程类
		 */
		/**
		 *	Timer类：定时器类。执行定时任务的。
		 *	作用：
		 *		1. 定时上传（闲时上传）
		 *		2. 断点续传（配合iO中RandomAccessFile类一起使用）
		 *	使用：
		 *		1. 创建对象
		 *			Timer() 创建一个新的定时器对象
		 *			Timer(String name) 创建一个新的定时器，其相关线程具有指定的名称
		 *		2. 调用方法
		 *			1.void schedule(TimerTask task, Date time) 在指定的时间执行指定的任务  
					2.void schedule(TimerTask task, long delay) 
						在指定的毫秒数之后执行指定的任务。  
					3.void schedule(TimerTask task, Date firstTime, long period) 
						从指定 的时间开始 ，间隔指定的毫秒数重复的执行
					4.void schedule(TimerTask task, long delay, long period) 
						从指定 的时间延迟后 ，间隔指定的毫秒数重复的执行
					5.void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 
						从指定 的时间开始 ，间隔指定的毫秒数重复的执行 (如果当期覅人Time是过去时间，会一次性将所有缺少的任务执行完毕)
					6.void scheduleAtFixedRate(TimerTask task, long delay, long period) 
						从指定 的时间延迟后 ，间隔指定的毫秒数重复的执行(不能执行过去任务，否则会抛出异常，delay不能为负数)
					7. void cancel() 终止当前任务。
		 */
	}
}
